package com.example.ymm.modules1.service.impl.sys;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.ymm.base.BaseServiceImpl;
import com.example.ymm.bo.YmUserDetails;
import com.example.ymm.dto.Constants;
import com.example.ymm.model.*;
import com.example.ymm.model.em.EmLoginPlatform;
import com.example.ymm.modules1.entity.my.sys.SysUser;
import com.example.ymm.modules1.entity.my.user.DbUser;
import com.example.ymm.modules1.mapper.my.sys.SysUserMapper;
import com.example.ymm.modules1.service.dto.SysUserQueryCriteria;
import com.example.ymm.modules1.service.sys.SysUserService;
import com.example.ymm.modules1.service.user.DbUserService;
import com.example.ymm.util.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Transactional
@Slf4j
public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser> implements SysUserService, UserDetailsService {

    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Value("${jwt.tokenHeader}")
    private String tokenHeader;
    @Value("${jwt.tokenHead}")
    private String tokenHead;
    @Value("${jwt.expiration}")
    private Long expiration;
    @Autowired
    DbUserService dbUserService;

    @Override
    public TableList<SysUser> list(SysUserQueryCriteria criteria, YmPageDto pageDto) {
        IPage<SysUser> page = new Page<SysUser>(pageDto.getPage(),pageDto.getPageSize());
        baseMapper.selectPage(page,QueryHelpPlus.getPredicate(SysUser.class, criteria));
        TableList<SysUser> tableList=new TableList(page);
        return tableList;
    }

    public List<SysUser> queryAll(SysUserQueryCriteria criteria) {
        List<SysUser> result =baseMapper.selectList(QueryHelpPlus.getPredicate(SysUser.class, criteria));
        return result;
    }

    @Override
    public SysUser findByUserName(String userName) {
        SysUserQueryCriteria criteria=new SysUserQueryCriteria();
        criteria.setUserName(userName);

        LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysUser::getUserName,userName);
        List<SysUser> sysUsers = baseMapper.selectList(wrapper);
        SysUser sysUser=null;
        if(UtilValidate.isNotEmpty(sysUsers)){
            sysUser=sysUsers.get(0);
        }
        return sysUser;
    }

    public YmUserDetails loadUserByUsername(String username){
        //获取用户信息
        SysUser user = findByUserName(username);
        if (user != null) {

            YmUserDetails yhUserDetails = getUserDetailBySysUser(user);

            return yhUserDetails;
        }
        throw new UsernameNotFoundException("用户名或密码错误");
    }

    public YmUserDetails getUserDetailBySysUser(SysUser sysUser){
        UserLogin userLogin=new UserLogin();
    //    userLogin.setPlatform(EmLoginPlatform.pc_3.getType());
        userLogin.setSysUser(sysUser);
        userLogin.setId(sysUser.getSysUserId());
        userLogin.setPassword(sysUser.getPassWord());
        userLogin.setUserName(sysUser.getUserName());
        YmUserDetails yhUserDetails = new YmUserDetails(userLogin);
        return  yhUserDetails;
    }

    public SysUser addUser(SysUser entity) {

        if(UtilValidate.isEmpty(entity.getSysUserId())){
            entity.setState(Constants.STATUS_ACTIVE);
        }

        if(UtilValidate.isNotEmpty(entity.getPassWord())){
            String encodePassword = passwordEncoder.encode(entity.getPassWord());
            entity.setPassWord(encodePassword);
        }
        if(UtilValidate.isEmpty(entity.getSysUserId())){
            saveOrUpdate(entity);
        }else{
            updateById(entity);
        }
        return entity;
    }

    @Override
    public CommonResult login(UserLoginParam userLoginParam) {
        String token = null;
        UserLogin userLogin=null;
        Map<String,Object> map=new HashMap<>();
        //密码需要客户端加密后传递
        try {

            SysUser sysUser2 = findByUserName(userLoginParam.getUserName());

            //管理员账号登录逻辑
            if(UtilValidate.isNotEmpty(sysUser2)){
                YmUserDetails userDetails = loadUserByUsername(userLoginParam.getUserName());
                Map<String, Object> stringObjectMap = sysUserLogin(userDetails, userLoginParam);
                 token= (String) stringObjectMap.get("token");
                 userLogin=(UserLogin) stringObjectMap.get("userLogin");
                 SysUser sysUser= (SysUser) stringObjectMap.get("sysUser");
                List<String> roleList=new ArrayList<>();
                roleList.add(sysUser.getRoleValue());
                userLogin.setRoleList(roleList);
                String s = JSONObject.toJSONString(userLogin);
                redisUtil.set(RedisKeyManager.pc_token_key+token, s,expiration);
                map.put("token",tokenHead+token);
                map.put("userId",sysUser.getSysUserId());
                map.put("roleList",roleList);
                map.put("homePath","/dashboard/analysis");
                map.put("permission",new ArrayList<>());
                map.put("nickName",sysUser.getNickName());
                map.put("userName",sysUser.getUserName());
                return CommonResult.success(map,"登录成功!");
            }

            DbUser user = dbUserService.findByUserName(userLoginParam.getUserName());
            if(UtilValidate.isNotEmpty(user)){
                if(UtilValidate.isEmpty(user.getPwd())){
                    return CommonResult.error("未开启账号登录功能,请联系管理员开通!");
                }
                if(!user.getPwd().equals(userLoginParam.getPassWord())){
                    return CommonResult.error("密码错误!");
                }
                CommonResult commonResult = dbUserService.loginByUserId(user.getUserId());
                return commonResult;
            }
            return CommonResult.error("无此账号，请联系管理员");


            // cacheMapService.setUserLogin(pdUserLogin.getUserId(),userDetails);

        } catch (AuthenticationException e) {
            log.warn("登录异常:{}", e.getMessage());
            return CommonResult.error(e.getMessage());
        }
    }

    Map<String,Object> sysUserLogin(YmUserDetails userDetails,UserLoginParam userLoginParam) {
        Map<String,Object> result=new HashMap<>();
        if(!passwordEncoder.matches(userLoginParam.getPassWord(),userDetails.getPassword())){
            throw new BadCredentialsException("账号或密码不正确");
        }
        UserLogin userLogin = userDetails.getUserLogin();
        userLogin.setPlatform(EmLoginPlatform.pc_3.getType());
        SysUser sysUser = userLogin.getSysUser();
        if(Constants.STATUS_DISABLED== sysUser.getState()){
            throw new BadCredentialsException("该账号已被冻结，请联系管理员.");
        }
        String token = jwtTokenUtil.generateToken(userDetails);
        // userDetails.setToken(token);
        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authentication);
        result.put("token",token);
        result.put("userLogin",userLogin);
        result.put("sysUser",sysUser);
        return result;
    }
}
